package top.amot.forceview.drawitem.node

import android.content.Context
import android.graphics.Canvas
import android.graphics.PointF
import top.amot.forceview.drawitem.AbstractDrawItem
import top.amot.forceview.drawitem.LinkPointPosition
import top.amot.forceview.model.AbstractNode
import top.amot.forceview.model.Node
import top.amot.forceview.theme.I_Theme
import kotlin.math.round
import kotlin.math.roundToInt
import kotlin.math.sqrt

class CircleNodeDrawItem(context: Context): AbstractDrawItem<Node>(context) {
    override fun isType(node: AbstractNode): Boolean {
        return node is Node
    }

    override fun measure(node: Node) {

    }

    override fun drawItem(canvas: Canvas, theme: I_Theme, node: Node, isSelectNode: Boolean) {

        val cx = node.x
        val cy = node.y
        val paint = theme.paint
        paint.color = theme.getColor(node.level)
        canvas.drawCircle(cx, cy, node.radius, paint)
        val text = node.text?:""

        val textBaseline = theme.textBaseline
        val textHeight = theme.textHeight
        val w =
            Math.sqrt((4 * node.radius * node.radius - textHeight * textHeight).toDouble()) - theme.padding * 2
        val textPaint = theme.textPaint
        val textWidth = textPaint.measureText(text)
        var n: Float
        if (w >= textWidth) { // 一行能装下
            canvas.drawText(text, cx, cy - textBaseline, textPaint)
        } else { // 一行装不下
            val th = textHeight * 2
            // 如果能够排成两行，并且排成两行之后，每行减去 padding 之后还能装下内容
            var ww=0
            if (th > node.radius && sqrt(4 * node.radius * node.radius - th * th) - theme.padding * 2.also {
                    ww = it
                } > 0) {
                val end = round(ww / textWidth * text.length).toInt()
                if (end < text.length) {
                    canvas.drawText(
                        text.substring(0, end),
                        cx,
                        cy - textHeight * 0.5f - textBaseline,
                        textPaint
                    )
                    // 两行都装不下，就省略
                    val t: String = if (textWidth > 2 * ww) {
                        text.substring(end, 2 * end - 1) + ".."
                    } else {
                        text.substring(end)
                    }
                    canvas.drawText(t, cx, cy + textHeight * 0.5f - textBaseline, textPaint)
                } else {
                    canvas.drawText(text, cx, cy - textBaseline, textPaint)
                }
            } else {
                val end = (w.toFloat() / textWidth * text.length).roundToInt()
                val t = text.substring(0, end - 1) + ".."
                canvas.drawText(t, cx, cy - textBaseline, textPaint)
            }
        }
    }

    override fun calcLinkPoint(node: Node, position: LinkPointPosition): PointF {
        return when(position){
            LinkPointPosition.TOP ->{
                PointF(node.x, (node.y-node.radius))
            }
            LinkPointPosition.BOTTOM->{
                PointF(node.x, (node.y+node.radius))
            }
            LinkPointPosition.LEFT->{
                PointF((node.x-node.radius), node.y)
            }
            LinkPointPosition.RIGHT->{
                PointF((node.x+node.radius), node.y)
            }
        }
    }

    override fun containPoint(node: Node, x: Float, y: Float): Boolean {
        val dx = x - node.x
        val dy = y - node.y
        val d2 = dx * dx + dy * dy
        val radius2=node.radius*node.radius
        if (d2 < radius2) {
            return true
        }
        return false
    }


}